package com.songlanyun.modules.order.controller.admin;

import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

//import org.apache.shiro.authz.annotation.RequiresPermissions;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.songlanyun.common.annotation.AuthIgnore;
import com.songlanyun.common.annotation.RepeatSubmit;
import com.songlanyun.common.annotation.SysLog;
import com.songlanyun.common.enums.CommentConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.*;
import com.songlanyun.common.utils.importverify.ImportVerifyHandler;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.modules.comment.service.OrderGoodsCommentService;
import com.songlanyun.modules.order.entity.ChildOrder;
import com.songlanyun.modules.order.model.dto.UpdateOrderGoodsPriceDTO;
import com.songlanyun.modules.order.model.vo.OrderVO;
import com.songlanyun.modules.order.model.vo.UserOrderRightsSlimStatisticsVo;
import com.songlanyun.modules.order.model.vo.UserOrderSlimStatisticsVo;
import com.songlanyun.modules.order.model.vo.UserOrderStatisticsVo;
import com.songlanyun.modules.rabbitmq.mq.producer.SendOrderOrRightsOrderMsgService;
import com.songlanyun.modules.rights.service.RightsOrderService;
import com.songlanyun.modules.ship.entity.OrderPackage;
import com.songlanyun.modules.ship.model.dto.BranchShipVO;
import com.songlanyun.modules.ship.service.OrderPackageService;
import com.songlanyun.modules.shop.entity.ShopEntity;
import com.songlanyun.modules.shop.service.ShopService;
import com.songlanyun.modules.user.controller.AbstractController;
import com.songlanyun.modules.user.dao.SysUserDao;
import com.songlanyun.modules.user.entity.SysUserEntity;
import jodd.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.service.OrderService;
import org.springframework.web.multipart.MultipartFile;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.io.FileReader;
import java.io.IOException;

/**
 * 销售系统中的主订单
 *
 * @author lubo
 * @email sunlightcs@gmail.com
 * @date 2020-11-16 14:14:42
 */
@RestController
@RequestMapping("admin/saleorder")
public class OrderAdminController extends AbstractController {
    @Autowired
    private OrderService orderService;

    @Autowired
    private RightsOrderService rightsOrderService;
    @Autowired
    private OrderGoodsCommentService orderGoodsCommentService;
    @Autowired
    private ImportVerifyHandler importVerifyHandler;
    @Autowired
    private ThreadPoolExecutor executor;

    @Autowired
    private OrderPackageService orderPackageService;

    @Autowired
    private SendOrderOrRightsOrderMsgService sendOrderOrRightsOrderMsgService;

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private ShopService shopService;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 商家的订单消费订单列表
     * params参数说明
     * marketing_type (0无活动，1秒杀，2拼团）
     * order_code 订单编号
     * shipment_mode 出货方式（0物流，1自提）
     * pay_order_code 支付订单号
     * transaction_status 交易状态（0已下单,待支付，1待发货（待备货） 3,"待收货（待自提）",5交易完成
     * third  是否是第三方商品（-1，0不是第三方商品，1是第三方商品）
     * receiver 收货人
     * mobile 收货人手机
     * startTime 开始时间
     * endTime 结束时间
     * withClosed 包含关闭的订单
     * page 当前第几页（默认第一页）
     * limit 每页多少条 （默认每页10条）
     */
    @RequestMapping("/shop/page")
    //@RequiresPermissions("order:saleorder:list")
    public R shopOrderPage(@RequestParam Map<String, Object> params) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 处理查询参数：startTime
        String startTime = String.valueOf(params.get("startTime"));
        if(StringUtils.isNotBlank(startTime) && !StringUtils.equalsIgnoreCase("null",startTime)){
            Date startDate = null;
            try {
                startDate = sdf.parse(startTime);
            } catch (ParseException e) {
                //
            }
            params.put("startTime", startDate);
        }

        // 处理查询参数：endTime
        String endTime = String.valueOf(params.get("endTime"));
        if(StringUtils.isNotBlank(endTime) && !StringUtils.equalsIgnoreCase("null",endTime)){
            Date endDate = null;
            try {
                endDate = sdf.parse(endTime);
            } catch (ParseException e) {
                //
            }
            params.put("endTime", endDate);
        }

        // 处理查询参数：withClosed
        String withClosed = String.valueOf(params.get("withClosed"));
        if(StringUtils.isNotBlank(withClosed) && !StringUtils.equalsIgnoreCase("null",withClosed)){
            Boolean withClosedVal = null;
            try {
                withClosedVal = Boolean.parseBoolean(withClosed);
            } catch (Exception e) {
                //
            }

            if(withClosedVal == null || !withClosedVal){
                params.put("withClosed", 0);
            } else {
                params.put("withClosed", 1);
            }
        }

        params.put("shop_id", getShopId());
        PageUtils page = orderService.shopOrderPage(params);
        return R.ok().put("page", page);
    }

    /**
     * 区域代理订单分页
     * @param params
     * @return
     */
    @RequestMapping("/areaagent/page")
    //@RequiresPermissions("order:saleorder:list")
    public R areaOrderPage(@RequestParam Map<String, Object> params) {
        params.put("area_agent_id", getAreaAgentId());
        PageUtils page = orderService.areaOrdersPage(params);
        return R.ok().put("page", page);
    }

    /**
     * 商家的订单服务订单列表
     * params参数说明
     * order_code 订单编号
     * pay_order_code 支付订单号
     * transaction_status 交易状态（0已下单,待支付，1待发货（待备货） 3,"待收货（待自提，待使用）",5交易完成
     * mobile 客户手机号
     * page 当前第几页（默认第一页）
     * limit 每页多少条 （默认每页10条）
     */
    @RequestMapping("/shop/service/page")
    //@RequiresPermissions("order:saleorder:list")
    public R shopServiceOrderPage(@RequestParam Map<String, Object> params) {
        params.put("shop_id", getShopId());
        PageUtils page = orderService.shopServiceOrderPage(params);
        return R.ok().put("page", page);
    }

    /**
     * 平台服务订单列表
     * params参数说明
     * order_code 订单编号
     * pay_order_code 支付订单号
     * transaction_status 交易状态（0已下单,待支付，1待发货（待备货） 3,"待收货（待自提，待使用）",5交易完成
     * mobile 客户手机号

     * page 当前第几页（默认第一页）
     * limit 每页多少条 （默认每页10条）
     */
    @RequestMapping("service/all/page")
    //@RequiresPermissions("order:saleorder:list")
    public R serviceOrderOrderPage(@RequestParam Map<String, Object> params) {
        PageUtils page = orderService.shopServiceOrderPage(params);
        return R.ok().put("page", page);
    }


    /**
     * 平台查看所有订单列表
     * params参数说明
     * marketing_type (0无活动，1秒杀，2拼团）
     * shop_name (商家名称）
     * order_code 订单编号
     * shipment_mode 出货方式（0物流，1自提）
     * pay_order_code 支付订单号
     * third  是否是第三方商品（-1，0不是第三方商品，1是第三方商品）
     * transaction_status 交易状态（0已下单,待支付，1待发货（待备货） 3,"待收货（待自提）",5交易完成
     * receiver 收货人
     * mobile 收货人手机
     * startTime 开始时间
     * endTime 结束时间
     * withClosed 包含关闭的订单
     * page 当前第几页（默认第一页）
     * limit 每页多少条 （默认每页10条）
     */
    @RequestMapping("/all/page")
    //@RequiresPermissions("order:saleorder:list")
    public R allOrderPage(@RequestParam Map<String, Object> params) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 处理查询参数：startTime
        String startTime = String.valueOf(params.get("startTime"));
        if(StringUtils.isNotBlank(startTime) && !StringUtils.equalsIgnoreCase("null",startTime)){
            Date startDate = null;
            try {
                startDate = sdf.parse(startTime);
            } catch (ParseException e) {
                //
            }
            params.put("startTime", startDate);
        }

        // 处理查询参数：endTime
        String endTime = String.valueOf(params.get("endTime"));
        if(StringUtils.isNotBlank(endTime) && !StringUtils.equalsIgnoreCase("null",endTime)){
            Date endDate = null;
            try {
                endDate = sdf.parse(endTime);
            } catch (ParseException e) {
                //
            }
            params.put("endTime", endDate);
        }

        // 处理查询参数：withClosed
        String withClosed = String.valueOf(params.get("withClosed"));
        if(StringUtils.isNotBlank(withClosed) && !StringUtils.equalsIgnoreCase("null",withClosed)){
            Boolean withClosedVal = null;
            try {
                withClosedVal = Boolean.parseBoolean(withClosed);
            } catch (Exception e) {
                //
            }

            if(withClosedVal == null || !withClosedVal){
                params.put("withClosed", 0);
            } else {
                params.put("withClosed", 1);
            }
        }

        PageUtils page = orderService.allOrderPage(params);
        return R.ok().put("page", page);
    }


    /**
     * 商家查看订单详情
     */
    @RequestMapping("/shop/info/{id}")
    //@RequiresPermissions("order:saleorder:info")
    public R loadByShopKey(@PathVariable("id") Long id) {
        Order order = orderService.loadByShopKey(getShopId(), id);
        if (order == null) {
            return R.ok().put("data", null);
        }
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        switch (order.getOrderType()) {
            case SALE_ORDER:
                switch (order.getShipmentMode()) {
                    case PICK_UP:
                        order.loadOrderSelfTake();
                        break;
                    case EXPRESS:
                        order.loadOrderReceipt();
                        break;
                    default:
                        break;
                }
                break;
            case SERVICE_ORDER:
                childOrderList.forEach(o -> {
                    o.loadServiceCard().loadServiceItems();
                });
                order.loadServiceOrderContacts();
                break;
            default:

        }

        order.loadOperator(getShopId());
        return R.ok().put("data", order);
    }

    /**
     * 平台查看订单详情
     */
    @RequestMapping("/info/{id}")
    //@RequiresPermissions("order:saleorder:info")
    public R info(@PathVariable("id") Long id) {
        Order order = orderService.getById(id);
        if (order == null) {
            return R.ok().put("data", null);
        }
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        switch (order.getOrderType()) {
            case SALE_ORDER:
                switch (order.getShipmentMode()) {
                    case PICK_UP:
                        order.loadOrderSelfTake();
                        break;
                    case EXPRESS:
                        order.loadOrderReceipt();
                        break;
                    default:
                        break;
                }
                break;
            case SERVICE_ORDER:
                childOrderList.forEach(o -> {
                    o.loadServiceCard().loadServiceItems();
                });
                order.loadServiceOrderContacts();
                break;
            default:

        }

        return R.ok().put("data", order);
    }


    /**
     * 店铺查会员的订单统计数据
     *
     * @param userId
     * @return
     */
    @RequestMapping("/consume/statistics/{userId}")
    //@RequiresPermissions("order:saleorder:info")
    public R statistics(@PathVariable("userId") Long userId) {
        UserOrderStatisticsVo userOrderStatisticsVo = new UserOrderStatisticsVo();
        UserOrderSlimStatisticsVo userOrderSlimStatisticsVo = this.orderService.loadUserOrderSlimStatistics(getShopId(), userId);

        UserOrderRightsSlimStatisticsVo userOrderRightsSlimStatisticsVo = this.rightsOrderService.loadOrderRightsSlimStatistics(getShopId(), userId);

        //会员普通商品订单评价数量
        Integer evaluateNum = this.orderGoodsCommentService.goodsEvaluateNum(userId, getShopId(false), CommentConstant.CommentType.GENERAL);

        userOrderStatisticsVo.setUserOrderSlimStatistics(userOrderSlimStatisticsVo);
        userOrderStatisticsVo.setUserOrderRightsSlimStatistics(userOrderRightsSlimStatisticsVo);
        userOrderStatisticsVo.setGoodsEvaluateNum(evaluateNum);

        return R.ok().put("data", userOrderStatisticsVo);
    }


    /**
     * 平台查会员的订单统计数据
     *
     * @param userId
     * @return
     */
    @RequestMapping("/consume/platform-statistics/{userId}")
    //@RequiresPermissions("order:saleorder:info")
    public R platformStatistics(@PathVariable("userId") Long userId) {
        UserOrderStatisticsVo userOrderStatisticsVo = new UserOrderStatisticsVo();
        UserOrderSlimStatisticsVo userOrderSlimStatisticsVo = this.orderService.loadUserOrderSlimStatistics(0L, userId);

        UserOrderRightsSlimStatisticsVo userOrderRightsSlimStatisticsVo = this.rightsOrderService.loadOrderRightsSlimStatistics(0L, userId);
        //会员普通==商品订单评价数量
        Integer evaluateNum = this.orderGoodsCommentService.goodsEvaluateNum(userId, null, CommentConstant.CommentType.GENERAL);

        userOrderStatisticsVo.setUserOrderSlimStatistics(userOrderSlimStatisticsVo);
        userOrderStatisticsVo.setUserOrderRightsSlimStatistics(userOrderRightsSlimStatisticsVo);
        userOrderStatisticsVo.setGoodsEvaluateNum(evaluateNum);

        return R.ok().put("data", userOrderStatisticsVo);
    }

    /**
     * 订单商品改价
     *
     * @param dto
     * @return
     */
    @SysLog("订单商品改价")
    @RepeatSubmit(value = "5")
    @PutMapping("/update/price")
    public R updateGoodsPrice(@RequestBody UpdateOrderGoodsPriceDTO dto) {
        ValidatorUtils.validateEntity(dto);
        String admin = getUser().getUsername();
        this.orderService.updateGoodsPrice(getShopId(), dto, (remark) -> {
            this.sensitiveLogCreate("管理员：" + admin + "," + remark.toString());
            return null;
        });
        return R.ok();
    }

    /**
     * 平台商品订单导出
     *
     * params参数说明
     * marketing_type (0无活动，1秒杀，2拼团）
     * shop_name (商家名称）
     * order_code 订单编号
     * shipment_mode 出货方式（0物流，1自提）
     * pay_order_code 支付订单号
     * third  是否是第三方商品（-1，0不是第三方商品，1是第三方商品）
     * transaction_status 交易状态（0已下单,待支付，1待发货（待备货） 3,"待收货（待自提）",5交易完成
     * receiver 收货人
     * mobile 收货人手机
     * startTime 开始时间
     * endTime 结束时间
     * withClosed 包含关闭的订单
     */
    @GetMapping("/export")
    //@RequiresPermissions("usergains:distributionuserordergains:list")
    public void export(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 处理查询参数：startTime
        String startTime = String.valueOf(params.get("startTime"));
        if(StringUtils.isNotBlank(startTime) && !StringUtils.equalsIgnoreCase("null",startTime)){
            Date startDate = null;
            try {
                startDate = sdf.parse(startTime);
            } catch (ParseException e) {
                //
            }
            params.put("startTime", startDate);
        }

        // 处理查询参数：endTime
        String endTime = String.valueOf(params.get("endTime"));
        if(StringUtils.isNotBlank(endTime) && !StringUtils.equalsIgnoreCase("null",endTime)){
            Date endDate = null;
            try {
                endDate = sdf.parse(endTime);
            } catch (ParseException e) {
                //
            }
            params.put("endTime", endDate);
        }

        // 处理查询参数：withClosed
        String withClosed = String.valueOf(params.get("withClosed"));
        if(StringUtils.isNotBlank(withClosed) && !StringUtils.equalsIgnoreCase("null",withClosed)){
            Boolean withClosedVal = null;
            try {
                withClosedVal = Boolean.parseBoolean(withClosed);
            } catch (Exception e) {
                //
            }

            if(withClosedVal == null || !withClosedVal){
                params.put("withClosed", 0);
            } else {
                params.put("withClosed", 1);
            }
        }

        params.put("shop_id", getShopId());
        Long adminId = this.getAdminByToken(response);//校验token
        List<OrderVO> orderList = orderService.exportList(params);

        String fileName = "商品订单列表" + DateUtils.format(new Date(), "yyyy-MM-dd-HHmmss") + "_" + adminId + "." + "xls";
        ExportParams exportParams = new ExportParams("商品订单列表导出(" + orderList.size() + ")", "商品订单列表");

        Workbook sheets = ExcelExportUtil.exportExcel(exportParams, OrderVO.class, orderList);
        response.setContentType(new MimetypesFileTypeMap().getContentType("application/octet-stream"));// 设置response内容的类型

        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));// 设置头部信息
        sheets.write(response.getOutputStream());
        sheets.close();
    }

    /**
     * 平台商品订单导出
     *
     * params参数说明
     * marketing_type (0无活动，1秒杀，2拼团）
     * shop_name (商家名称）
     * order_code 订单编号
     * shipment_mode 出货方式（0物流，1自提）
     * pay_order_code 支付订单号
     * third  是否是第三方商品（-1，0不是第三方商品，1是第三方商品）
     * transaction_status 交易状态（0已下单,待支付，1待发货（待备货） 3,"待收货（待自提）",5交易完成
     * receiver 收货人
     * mobile 收货人手机
     * startTime 开始时间
     * endTime 结束时间
     * withClosed 包含关闭的订单
     */
    @GetMapping("/exportAll")
    @AuthIgnore
    //@RequiresPermissions("usergains:distributionuserordergains:list")
    public void exportAll(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 处理查询参数：startTime
        String startTime = String.valueOf(params.get("startTime"));
        if(StringUtils.isNotBlank(startTime) && !StringUtils.equalsIgnoreCase("null",startTime)){
            Date startDate = null;
            try {
                startDate = sdf.parse(startTime);
            } catch (ParseException e) {
                //
            }
            params.put("startTime", startDate);
        }

        // 处理查询参数：endTime
        String endTime = String.valueOf(params.get("endTime"));
        if(StringUtils.isNotBlank(endTime) && !StringUtils.equalsIgnoreCase("null",endTime)){
            Date endDate = null;
            try {
                endDate = sdf.parse(endTime);
            } catch (ParseException e) {
                //
            }
            params.put("endTime", endDate);
        }

        // 处理查询参数：withClosed
        String withClosed = String.valueOf(params.get("withClosed"));
        if(StringUtils.isNotBlank(withClosed) && !StringUtils.equalsIgnoreCase("null",withClosed)){
            Boolean withClosedVal = null;
            try {
                withClosedVal = Boolean.parseBoolean(withClosed);
            } catch (Exception e) {
                //
            }

            if(withClosedVal == null || !withClosedVal){
                params.put("withClosed", 0);
            } else {
                params.put("withClosed", 1);
            }
        }

        Long adminId = this.getAdminByToken(response);//校验token
        List<OrderVO> orderList = orderService.exportList(params);

        String fileName = "商品订单列表" + DateUtils.format(new Date(), "yyyy-MM-dd-HHmmss") + "_" + adminId + "." + "xls";
        ExportParams exportParams = new ExportParams("商品订单列表导出(" + orderList.size() + ")", "商品订单列表");

        Workbook sheets = ExcelExportUtil.exportExcel(exportParams, OrderVO.class, orderList);
        response.setContentType(new MimetypesFileTypeMap().getContentType("application/octet-stream"));// 设置response内容的类型

        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));// 设置头部信息
        sheets.write(response.getOutputStream());
        sheets.close();
    }

    /**
     * 导出待发货订单
     * @param params
     * @param response
     * @throws Exception
     */
    /**
     * 批量导出指定商家的待发货订单
     *
     * @param params
     * @param response
     * @throws Exception
     */
    @GetMapping("/export/waitship")
    @AuthIgnore
    //@RequiresPermissions("usergains:distributionuserordergains:list")
    public void exportWaitShip(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        Long adminId = this.getAdminByToken(response);//校验token
        Long shopId = this.getShopIdByAdmin(adminId);
        params.put("shop_id", shopId);
        List<BranchShipVO> orderList = orderService.exportWaitShip(params);

        String fileName = "待发货订单列表" + DateUtils.format(new Date(), "yyyy-MM-dd-HHmmss") + "_" + adminId + "." + "xls";
        ExportParams exportParams = new ExportParams("待发货订单列表导出(" + orderList.size() + ")", "待发货订单列表");

        Workbook sheets = ExcelExportUtil.exportExcel(exportParams, BranchShipVO.class, orderList);
        response.setContentType(new MimetypesFileTypeMap().getContentType("application/octet-stream"));// 设置response内容的类型

        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));// 设置头部信息
        sheets.write(response.getOutputStream());
        sheets.close();
    }

    /**
     * 导入设置好的发货订单文件，批量发货
     * @param multipartFile
     * @param response
     * @return
     * @throws Exception
     */
    @PostMapping("/import_ship")
    public R importUser(@RequestParam("file") MultipartFile multipartFile, HttpServletResponse response) throws Exception {
        Long shopId = this.getShopId();
        //获得excel中的数据
        Map<String, Object> map = ImportUtil.importExcel(1, 1, BranchShipVO.class, importVerifyHandler, multipartFile, true);
        List<BranchShipVO> importList = (List<BranchShipVO>) map.get("success");
        // 创建 Future 集合，用来存储 Future 实例
        List<Future<BranchShipVO>> futureList = new ArrayList<>();
        List<BranchShipVO> errorList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(importList)) {

            if (importList.size() > 0) {

                importList.forEach(importRow -> {
                    if (StringUtils.isNotEmpty(importRow.getLogisticCode())) {
                        //批量导入数据库
                        Future<BranchShipVO> future = executor.submit(new Callable<BranchShipVO>() {
                            @Override
                            public BranchShipVO call() throws Exception {
                                if (StringUtils.isEmpty(importRow.getLogisticCode())) {
                                    importRow.setErrorMsg("运单号没有填");
                                    return importRow;
                                }
                                try {
                                    OrderPackage orderPackage = orderPackageService.expressShipForImport(shopId, importRow);
                                    sendOrderOrRightsOrderMsgService.expressShipSuccessSendMsg(orderPackage);
                                } catch (Exception ex) {
                                    importRow.setErrorMsg(ex.getMessage());
                                    return importRow;
                                }
                                return null;
                            }
                        });
                        futureList.add(future);
                    }

                });

                List<BranchShipVO> resultList = new ArrayList<>();
                for (Future<BranchShipVO> future : futureList) {
                    // 获取每一个线程的返回结果，如果该线程未完成，会阻塞
                    BranchShipVO vo = future.get(30, TimeUnit.SECONDS);
                    if (vo != null) {
                        resultList.add(vo);
                    }
                }

                StringBuffer sbf = new StringBuffer();
                resultList.forEach(e ->
                {
                    sbf.append("第" + (e.getRowNum() + 1) + "行存在错误：" + e.getErrorMsg()+"\n");
                });

                if (StringUtil.isNotEmpty(sbf.toString())) {
                    throw new RRException(sbf.toString());
                }
            }
        }
        return R.ok();
    }

    /**
     * 批量更新物流信息
     */
    @PostMapping("/batch-to-update-logistic-info")
    public R batchToUpdateLogisticInfo() throws Exception {
        //Long shopId = this.getShopId();
        try {
            FileReader fileReader = new FileReader("D:/common-report-custom_so_main_list-一链金服科技-aa5d1c57-d011-4cc8-b69c-69d0fd3c3a44.csv");
            CSVParser csvParser = new CSVParser(fileReader, CSVFormat.DEFAULT);
            String sqlForLogisticsCodeUpdate  = " update yxt_sale_order_package_express " +
                                                " set express_code = 'JD' " +
                                                ",express_name = '京东快递' " +
                                                ",logistic_code = ? " +
                                                " where goods_package_id = " +
                                                " (select id from yxt_sale_order_package where order_code = ?) ";

            String sqlForLogisticsTraceUpdate = " update yxt_sale_order_package_express " +
                                                " set query_result = ? " +
                                                ",last_query_time = now() " +
                                                " where goods_package_id = " +
                                                " (select id from yxt_sale_order_package where order_code = ?) ";

            String sqlForOrderMobileQuery     = " select mobile from yxt_sale_order where order_code = ? ";

            int rowNum = 0;
            int batchSize = 100;
            int batchSN = 0;
            int batchRecordIndex = 0;
            List<Object[]> batchArgsForLogisticsCodeUpdate = null;
            for (CSVRecord csvRecord : csvParser.getRecords()) {

                String orderCode = csvRecord.get(0);
                String logisticCode = csvRecord.get(1);

                /** 批量更新物流单号
                if((batchRecordIndex = rowNum % batchSize) == 0) {
                    batchSN = rowNum/ batchSize + 1;
                    batchArgsForLogisticsCodeUpdate = new ArrayList<Object[]>();
                }

                batchArgsForLogisticsCodeUpdate.add(new Object[]{logisticCode,orderCode});

                if(batchRecordIndex == batchSize - 1) {
                    try {
                        System.out.println("正在更新第" + batchSN +"批订单。");
                        int[] effectedCount = jdbcTemplate.batchUpdate(sqlForLogisticsCodeUpdate, batchArgsForLogisticsCodeUpdate);
                        System.out.println("订单更新成功：" + Arrays.toString(effectedCount));
                    } catch (Exception ex) {
                        //
                    }
                }
                 */

                /** 批量更新物流跟踪信息
                String orderMobile = null;
                String logisticsTraces = null;
                try{
                    orderMobile = jdbcTemplate.queryForObject(sqlForOrderMobileQuery, String.class, orderCode);
                    logisticsTraces = orderService.queryExpressExpNo(logisticCode, orderMobile);
                } catch (Exception ex){
                    rowNum++;
                    continue;
                }

                if((batchRecordIndex = rowNum % batchSize) == 0) {
                    batchSN = rowNum/ batchSize + 1;
                    batchArgsForLogisticsCodeUpdate = new ArrayList<Object[]>();
                }

                batchArgsForLogisticsCodeUpdate.add(new Object[]{logisticsTraces, orderCode});

                if(batchRecordIndex == batchSize - 1) {
                    try {
                        System.out.println("正在更新第" + batchSN +"批订单。");
                        int[] effectedCount = jdbcTemplate.batchUpdate(sqlForLogisticsTraceUpdate, batchArgsForLogisticsCodeUpdate);
                        System.out.println("订单更新成功：" + Arrays.toString(effectedCount));
                    } catch (Exception ex) {
                        //
                    }
                }
                 */
                
                rowNum++;
            }
            csvParser.close();
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
        return R.ok();
    }

    protected Long getShopIdByAdmin(Long adminId) {
        SysUserEntity user = sysUserDao.selectById(adminId);

        if (user.getIsShop()) {
            ShopEntity shop = shopService.getShopByAdminId(user.getUserId(), false);
            if (shop != null) {
                return shop.getId();
            }
        }
        return 0L;
    }



}
